/* 
 * File:   newmain.cpp
 * Author: ben
 *
 * Created on March 29, 2009, 2:56 PM
 */

#include <stdlib.h>
#include "MyGraphClass.h"

#include <bitset>
#include <limits>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/simple_point.hpp>
#include <boost/graph/circle_layout.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/graph/random_layout.hpp>
#include <boost/progress.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <map>
#include <vector>
#include <boost/graph/fruchterman_reingold.hpp>
#include <boost/graph/fruchterman_reingold.hpp>
#include <boost/graph/random_layout.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/simple_point.hpp>
#include <boost/graph/edge_list.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
#include <map>
#include <vector>
#include <boost/random/linear_congruential.hpp>
#include <boost/progress.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <boost/config.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/bellman_ford_shortest_paths.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <iomanip>


using namespace boost;

int main(int argc, char** argv) {



    MyGraph *mgraph;
    mgraph  =   new MyGraph();
    mgraph->LoadXml("data","relationships.xml","weights.xml");
    typedef std::pair<int, int> Edge;
    Edge *edge_array;

    double *weights;
    int i,j,n,ns;
    int num_nodes,n_edges,N;

    edge_array  =   NULL;
    weights     =   NULL;

    num_nodes   =   mgraph->NumberVertices();
    N           =   num_nodes;

    n           =   0;
    for(i=0;i<mgraph->NumberVertices();i++){
        ns  =   n;
        n   =   n+mgraph->getNextMax(i);
        //cout << n << endl;

        edge_array  =   (Edge*) realloc (edge_array, n * sizeof(Edge));
        weights     =   (double*) realloc (weights, n * sizeof(double));
        for(j=0;j<mgraph->getNextMax(i);j++){
            edge_array[ns+j]    =   Edge(i,mgraph->getNext(i,j));
            weights[ns+j]       =   (double)pow(mgraph->getWeight(i,j),10);
            //weights[ns+j]       =   .5;
            //std::cout<< weights[ns+j] << endl;
            //cout << ns+j<< ":" << edge_array[ns+j].first << "\t,\t" << edge_array[ns+j].second << "\t w:" << weights[ns+j] << "," << mgraph->getWeight(i,j) <<  endl;
        }
    }
    n_edges     =   n;
    cout << "n_edges:" << n_edges << endl;
    cout << "edge_arr:" << sizeof(edge_array) << endl;


    //++++++++++++++++==========================================
    int n_vertices;
  n_vertices=N;


  // Specify the graph type and declare a graph object
  typedef edge_list < Edge*, Edge, std::ptrdiff_t, std::random_access_iterator_tag> Graph;
  Graph g(edge_array, edge_array + n_edges);

 
  int parent[n_vertices];
  for (int i = 0; i < n_vertices; ++i)
    parent[i] = i;
  double distance[n_vertices];
  std::fill(distance, distance + n_vertices, (std::numeric_limits < double >::max)());
  // Specify A as the source vertex
  distance[35] = 0;

  bool r = bellman_ford_shortest_paths(g, int (n_vertices),
                                       weight_map(make_iterator_property_map
                                                  (&weights[0],
                                                   get(edge_index, g),
                                                   weights[0])).
                                       distance_map(&distance[0]).
                                       predecessor_map(&parent[0]));

  if (r)
    for (int i = 0; i < n_vertices; ++i)
      std::cout << i << "\t" << distance[i]
        << "\t" << parent[i] << std::endl;
  else
    std::cout << "negative cycle" << std::endl;

    return (EXIT_SUCCESS);
}

